package com.atguigu.gmall.serviceutil.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author A
 * @version 1.0
 * @description: TODO
 * @date 2025/8/30 21:11
 */
@Slf4j
@EnableConfigurationProperties(AppThreadPoolProperties.class)
@Configuration
public class AppThreadPoolAutoConfig {

    //int corePoolSize, 核心线程数
    //int maximumPoolSize, 最大线程数(核心线程数和最大线程数的区别是：核心线程数在初始化时就创建，最大线程数可以扩充)
    //long keepAliveTime, 线程存活时间
    // TimeUnit unit, 时间单位
    // BlockingQueue<Runnable> workQueue, 任务队列 (任务队列是用来存放等待执行的任务的阻塞队列)
    // ThreadFactory threadFactory,  线程工厂
    // RejectedExecutionHandler handler ,  拒绝策略
    @Bean
    @Primary
    public ThreadPoolExecutor coreThreadPool(AppThreadPoolProperties properties,
                                             @Value("${spring.application.name:DEFAULT_APP_NAME}") String appName) {
        log.info("初始化核心线程池, corePoolSize={}, maxPoolSize={}, keepAliveTime={}, unit={}, queueCapacity={}, appName={}",
                properties.getCorePoolSize(),
                properties.getMaxPoolSize(),
                properties.getKeepAliveTime(),
                properties.getUnit(),
                properties.getQueueCapacity(),
                appName);
        return new ThreadPoolExecutor(properties.getCorePoolSize(),
                properties.getMaxPoolSize(),
                properties.getKeepAliveTime(),
                properties.getUnit(),
                new LinkedBlockingQueue<>(properties.getQueueCapacity()),
                new AppThreadFactory(appName+"-"+"core"),
                properties.getRejectedExecutionHandler());
    }
    @Bean
    public ThreadPoolExecutor otherThreadPool(AppThreadPoolProperties properties,
                                             @Value("${spring.application.name:DEFAULT_APP_NAME}") String appName) {
        log.info("初始化其他线程池, corePoolSize={}, maxPoolSize={}, keepAliveTime={}, unit={}, queueCapacity={}, appName={}",
                properties.getCorePoolSize()/2,
                properties.getMaxPoolSize()/2,
                properties.getKeepAliveTime(),
                properties.getUnit(),
                properties.getQueueCapacity()/2,
                appName);
        return new ThreadPoolExecutor(properties.getCorePoolSize()/2,
                properties.getMaxPoolSize()/2,
                properties.getKeepAliveTime(),
                properties.getUnit(),
                new LinkedBlockingQueue<>(properties.getQueueCapacity()/2),
                new AppThreadFactory(appName+"-"+"other"),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }
   static class  AppThreadFactory implements ThreadFactory {
        private final String appName;
        private final AtomicInteger threadNum = new AtomicInteger(1);
        public AppThreadFactory(String appName){
            this.appName=appName;
        }
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("["+appName + "]" + "-" + threadNum.getAndIncrement());

            return thread;
        }
    }

}
